#include "CCanvas.h"
#include "CAbacus.h"


CCanvas::CCanvas()
{
    lphbr[0] = CreateSolidBrush(RGB(192, 192, 192));
    lphbr[1] = CreateSolidBrush(RGB(192, 192, 255));
    lphbr[2] = CreateSolidBrush(RGB(255, 192, 192));
    lphbr[3] = CreateSolidBrush(RGB(255, 192, 255));
    lphbr[4] = CreateSolidBrush(RGB(192, 255, 192));
    lphbr[5] = CreateSolidBrush(RGB(192, 255, 255));
    lphbr[6] = CreateSolidBrush(RGB(255, 255, 192));
    iStoneType = ID_ELLIPSE;
    frame_width = abacus.m_digit * DIGITAL_INTERVAL;
    stick_top = TOP_Y + FRAME_THICKNESS / 2;
    up_stone_top = TOP_Y + FRAME_THICKNESS;
    beam_top = up_stone_top + STONE_HEIGHT * 2;
    down_stone_top = beam_top + BEAM_THICKNESS;
    down_frame_top = down_stone_top + STONE_HEIGHT * 5;
    stick_left = LEFT_X + DIGITAL_INTERVAL / 2 - STICK_DIAMETER / 2;
    stone_left = LEFT_X + DIGITAL_INTERVAL / 2 - STONE_WIDTH / 2;
    stick_height = BEAM_THICKNESS + STONE_HEIGHT * 7 + FRAME_THICKNESS;
    text_x = LEFT_X + DIGITAL_INTERVAL / 2;
    text_y = TOP_Y / 2;
    m_hFont = CreateFont(40, 15, 0, 0, 1, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FF_ROMAN, "Times New Roman");
    //ctor
}


void CCanvas::OnPaint(HWND hWnd, HDC hdc)
{
    RECT rect;
    GetClientRect(hWnd, &rect);
    SelectObject(hdc, GetStockObject(WHITE_BRUSH));
    SelectObject(hdc, GetStockObject(WHITE_PEN));
    Rectangle(hdc, rect.left, rect.top, rect.right, rect.bottom);
    DrawSticks(hdc);
    DrawFramesAndBeam(hdc);
    switch (iStoneType)
    {
    case ID_ELLIPSE:
        DrawEllipticStones(hdc);
        break;
    case ID_HEXAGON:
        DrawHexagonalStones(hdc);
        break;
    }
    DrawNumber(hdc);
}

void CCanvas::OnLeftButtonUp(int x, int y, HWND hWnd)
{
    int i, j, k;
    i = (x - LEFT_X) / DIGITAL_INTERVAL;
    j = (y - up_stone_top) / STONE_HEIGHT;
    k = (y - down_stone_top) / STONE_HEIGHT;
    if (i >= 0 && i < int(abacus.m_digit))
    {
        if (j >= 0 && j < 2)
        {
            if (j == 0 && abacus.m_lpComponents[i] < 5)
            {
                abacus.m_lpComponents[i] += 5;
            }
            if (j == 1 && abacus.m_lpComponents[i] >= 5)
            {
                abacus.m_lpComponents[i] -= 5;
            }
        }
        if (k >= 0 && k < 5)
        {
            if (k < int(abacus.m_lpComponents[i] % 5))
            {
                abacus.m_lpComponents[i] -= (abacus.m_lpComponents[i] % 5 - k);
            }
            if (k > int(abacus.m_lpComponents[i] % 5))
            {
                abacus.m_lpComponents[i] += (k - abacus.m_lpComponents[i] % 5);
            }
        }
    }
    InvalidateRect(hWnd, NULL, true);
}

void CCanvas::OnKeyUp(char cKeyCode, HWND hWnd)
{
    switch(cKeyCode)
    {
    case 'c':
    case 'C':
        abacus.data_clear();
        break;
    case '0':
    case '1':
    case '2':
    case '3':
    case '4':
    case '5':
    case '6':
    case '7':
    case '8':
    case '9':
        abacus.move_right((unsigned int)(cKeyCode - int('0')));
        break;
    }
    InvalidateRect(hWnd, NULL, true);
}

void CCanvas::DrawSticks(HDC hdc)
{
    unsigned int i;
    SelectObject(hdc, GetStockObject(BLACK_PEN));
    SelectObject(hdc, GetStockObject(WHITE_BRUSH));
    for (i = 0; i < abacus.m_digit; ++i)
    {
        Rectangle(hdc, stick_left + i * DIGITAL_INTERVAL, stick_top, stick_left + i * DIGITAL_INTERVAL + STICK_DIAMETER, stick_top + stick_height);
    }
}

void CCanvas::DrawFramesAndBeam(HDC hdc)
{
    SelectObject(hdc, GetStockObject(BLACK_PEN));
    SelectObject(hdc, GetStockObject(WHITE_BRUSH));
    Rectangle(hdc, LEFT_X, TOP_Y, LEFT_X + frame_width, TOP_Y + FRAME_THICKNESS);
    Rectangle(hdc, LEFT_X, beam_top, LEFT_X + frame_width, beam_top + BEAM_THICKNESS);
    Rectangle(hdc, LEFT_X, down_frame_top, LEFT_X + frame_width, down_frame_top + FRAME_THICKNESS);
}

void CCanvas::DrawEllipticStones(HDC hdc)
{
    unsigned int i, j;
    for (i = 0; i <abacus.m_digit; ++i)
    {
        SelectObject(hdc, lphbr[i % 7]);
        if (abacus.m_lpComponents[i] < 5)
        {
            Ellipse(hdc, stone_left + i * DIGITAL_INTERVAL, up_stone_top, stone_left + i * DIGITAL_INTERVAL + STONE_WIDTH, up_stone_top + STONE_HEIGHT);
        }
        else
        {
            Ellipse(hdc, stone_left + i * DIGITAL_INTERVAL, up_stone_top + STONE_HEIGHT, stone_left + i * DIGITAL_INTERVAL + STONE_WIDTH, up_stone_top + STONE_HEIGHT * 2);
        }
        if (abacus.m_lpComponents[i] % 5 > 0)
        {
            for (j = 0; j < abacus.m_lpComponents[i] % 5; ++j)
            {
                Ellipse(hdc, stone_left + i * DIGITAL_INTERVAL, down_stone_top + STONE_HEIGHT * j, stone_left + i * DIGITAL_INTERVAL + STONE_WIDTH, down_stone_top + STONE_HEIGHT * j + STONE_HEIGHT);
            }
        }
        if (abacus.m_lpComponents[i] % 5 < 4)
        {

            for (j = 0; j < 4 - abacus.m_lpComponents[i] % 5; ++j)
            {
                Ellipse(hdc, stone_left + i * DIGITAL_INTERVAL, down_frame_top - STONE_HEIGHT * (j + 1), stone_left + i * DIGITAL_INTERVAL + STONE_WIDTH, down_frame_top - STONE_HEIGHT * (j + 1) + STONE_HEIGHT);
            }
        }
    }
}

void CCanvas::DrawHexagonalStones(HDC hdc)
{
    unsigned int i, j;
    POINT lpVertices[6];
    for (i = 0; i <abacus.m_digit; ++i)
    {
        SelectObject(hdc, lphbr[i % 7]);
        if (abacus.m_lpComponents[i] < 5)
        {
            lpVertices[0] = {LONG(stone_left + i * DIGITAL_INTERVAL), LONG(up_stone_top + STONE_HEIGHT / 2)};
            lpVertices[1] = {LONG(stone_left + i * DIGITAL_INTERVAL + STONE_WIDTH / 4), LONG(up_stone_top + STONE_HEIGHT)};
            lpVertices[2] = {LONG(stone_left + i * DIGITAL_INTERVAL + STONE_WIDTH * 3 / 4), LONG(up_stone_top + STONE_HEIGHT)};
            lpVertices[3] = {LONG(stone_left + i * DIGITAL_INTERVAL + STONE_WIDTH), LONG(up_stone_top + STONE_HEIGHT / 2)};
            lpVertices[4] = {LONG(stone_left + i * DIGITAL_INTERVAL + STONE_WIDTH * 3 / 4), LONG(up_stone_top)};
            lpVertices[5] = {LONG(stone_left + i * DIGITAL_INTERVAL + STONE_WIDTH / 4), LONG(up_stone_top)};
            Polygon(hdc, lpVertices, 6);
        }
        else
        {
            lpVertices[0] = {LONG(stone_left + i * DIGITAL_INTERVAL), LONG(up_stone_top + STONE_HEIGHT * 3 / 2)};
            lpVertices[1] = {LONG(stone_left + i * DIGITAL_INTERVAL + STONE_WIDTH / 4), LONG(up_stone_top + STONE_HEIGHT * 2)};
            lpVertices[2] = {LONG(stone_left + i * DIGITAL_INTERVAL + STONE_WIDTH * 3 / 4), LONG(up_stone_top + STONE_HEIGHT * 2)};
            lpVertices[3] = {LONG(stone_left + i * DIGITAL_INTERVAL + STONE_WIDTH), LONG(up_stone_top + STONE_HEIGHT * 3 / 2)};
            lpVertices[4] = {LONG(stone_left + i * DIGITAL_INTERVAL + STONE_WIDTH * 3 / 4), LONG(up_stone_top + STONE_HEIGHT)};
            lpVertices[5] = {LONG(stone_left + i * DIGITAL_INTERVAL + STONE_WIDTH / 4), LONG(up_stone_top + STONE_HEIGHT)};
            Polygon(hdc, lpVertices, 6);
        }
        if (abacus.m_lpComponents[i] % 5 > 0)
        {
            for (j = 0; j < abacus.m_lpComponents[i] % 5; ++j)
            {
                lpVertices[0] = {LONG(stone_left + i * DIGITAL_INTERVAL), LONG(down_stone_top + STONE_HEIGHT * (j * 2 + 1) / 2)};
                lpVertices[1] = {LONG(stone_left + i * DIGITAL_INTERVAL + STONE_WIDTH / 4), LONG(down_stone_top + STONE_HEIGHT * (j + 1))};
                lpVertices[2] = {LONG(stone_left + i * DIGITAL_INTERVAL + STONE_WIDTH * 3 / 4), LONG(down_stone_top + STONE_HEIGHT * (j + 1))};
                lpVertices[3] = {LONG(stone_left + i * DIGITAL_INTERVAL + STONE_WIDTH), LONG(down_stone_top + STONE_HEIGHT * (j * 2 + 1) / 2)};
                lpVertices[4] = {LONG(stone_left + i * DIGITAL_INTERVAL + STONE_WIDTH * 3 / 4), LONG(down_stone_top + STONE_HEIGHT * j)};
                lpVertices[5] = {LONG(stone_left + i * DIGITAL_INTERVAL + STONE_WIDTH / 4), LONG(down_stone_top + STONE_HEIGHT * j)};
                Polygon(hdc, lpVertices, 6);
           }
        }
        if (abacus.m_lpComponents[i] % 5 < 4)
        {

            for (j = 0; j < 4 - abacus.m_lpComponents[i] % 5; ++j)
            {
                lpVertices[0] = {LONG(stone_left + i * DIGITAL_INTERVAL), LONG(down_frame_top - STONE_HEIGHT * (j * 2 + 1) / 2)};
                lpVertices[1] = {LONG(stone_left + i * DIGITAL_INTERVAL + STONE_WIDTH / 4), LONG(down_frame_top - STONE_HEIGHT * j)};
                lpVertices[2] = {LONG(stone_left + i * DIGITAL_INTERVAL + STONE_WIDTH * 3 / 4), LONG(down_frame_top - STONE_HEIGHT * j)};
                lpVertices[3] = {LONG(stone_left + i * DIGITAL_INTERVAL + STONE_WIDTH), LONG(down_frame_top - STONE_HEIGHT * (j * 2 + 1) / 2)};
                lpVertices[4] = {LONG(stone_left + i * DIGITAL_INTERVAL + STONE_WIDTH * 3 / 4), LONG(down_frame_top - STONE_HEIGHT * (j + 1))};
                lpVertices[5] = {LONG(stone_left + i * DIGITAL_INTERVAL + STONE_WIDTH / 4), LONG(down_frame_top - STONE_HEIGHT * (j + 1))};
                Polygon(hdc, lpVertices, 6);
            }
        }
    }
}

void CCanvas::DrawNumber(HDC hdc)
{
    unsigned int i;
    bool bShowZero;
    RECT rect;
    int width = 30;
    int height = 40;
    char lpstrData[4];
    SelectObject(hdc, m_hFont);
    bShowZero = false;
    for (i = 0; i < abacus.m_digit; ++i)
    {
        if (abacus.m_lpComponents[i] > 0 || bShowZero || i == abacus.m_digit - 1)
        {
            bShowZero = true;
            wsprintf(lpstrData, "%d", abacus.m_lpComponents[i]);
            rect.left = text_x + DIGITAL_INTERVAL * i - width / 2;
            rect.top = text_y - height / 2;
            rect.right = text_x + DIGITAL_INTERVAL * i + width / 2;
            rect.bottom = text_y + height / 2;
            DrawText(hdc, lpstrData, 1, &rect, DT_VCENTER | DT_CENTER);
        }
    }
}
